/**
 * @File name: init.h
 * @Synopsis:
 * @Author: xing.dai@aliyun.com
 * @Version: 0.0.1
 * @Date: 2018-12-24 20:45
 */

#ifndef __INIT_H__
#define __INIT_H__

/* Warning:
 *	Align must be important!
 *	Must execute "readelf -S xxxx" to see this segment align 4!
 *	The value of align is changed in ubuntu 64-bit
 */
#ifdef ARCH_LINUX
struct _config_init {
    int (*init)();
};

#define _CONFIG_INIT_DEF(type, init_name, init_func, init_data, level)		\
	static struct _config_init __config_init_##init_name	\
	__attribute__((used, section("."#type"_init_array_"#level))) = {	\
		.init = init_func,	\
	}
#else
struct _config_init {
    int (*init)(struct _config_init *);
    char *name;
    void *data;
};

#ifdef __GNUC__
#define INIT_SECTION_NAME_PREFIX	"."		/* GCC */
#else
#define INIT_SECTION_NAME_PREFIX	"__"	/* ARMCC */
#endif

#define _CONFIG_INIT_DEF(type, init_name, init_func, init_data, level)		\
	static struct _config_init __config_init_##init_name	\
	__attribute__((used, section(INIT_SECTION_NAME_PREFIX#type"_init_array_"#level))) = {	\
		.init = init_func,	\
		.name = #init_name,	\
        .data = (void *)init_data,	\
	}
#endif
#define CONFIG_HW_INIT(name, func, data, level)	\
	_CONFIG_INIT_DEF(hw, name, func, data, level)
#define CONFIG_SW_INIT(name, func, data, level)	\
	_CONFIG_INIT_DEF(sw, name, func, data, level)

#define HW_INIT_LEVEL_0     0
#define HW_INIT_LEVEL_1     1
#define HW_INIT_LEVEL_2     2
#define HW_INIT_LEVEL_3     3

#define SW_INIT_LEVEL_0     0
#define SW_INIT_LEVEL_1     1
#define SW_INIT_LEVEL_2     2
#define SW_INIT_LEVEL_3     3

void hw_do_init(int level);
void sw_do_init(int level);
#endif

